# encoding=utf8
from trp.models import *
from utils.JsonResponse import JsonResponse, JsonResponseBadrequest
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from utils.decorators import *
from datetime import datetime
from django.db import transaction

from utils.JsonResponse import JsonResponse, JsonResponseBadrequest
from utils.decorators import *
from website.settings import LOGGER as logger
import json
from utils.utils import *
from django.db.models.query_utils import Q
from django.db.models import Sum
from trp.views.strategy import get_materialData_By_Traffic,get_tag_name,get_resource_area_name,get_Field_list,get_default_resource_strategy,get_default_traffic_strategy
from trp.views.material import __parse_material_weight
from trp.views.media import get_FieldsValue
from trp.views.traffic import traffic_bid_type,is_traffic_shared
from trp.views.costlog import get_cost_by_resource,get_media_cost_by_resource
from trp.views.cost import get_current_balance
from django.template.defaultfilters import floatformat
from utils.utils import date_range_array


@login_required
def main(request):   
    tid = request.GET.get("traffic") 
    account = request.user.account
    if account.is_admin():
        return render_to_response('trp/resource_admin.html',{'traffic':tid, 'user':request.user, 'page':'traffic'})
    elif account.is_platform_user():
        return render_to_response('trp/resource_platform.html',{'traffic':tid, 'user':request.user, 'page':'traffic'})
    elif account.is_vendor_user() or account.is_merchant_user():
        return render_to_response('trp/resource_merchant.html',{'traffic':tid, 'user':request.user, 'page':'traffic'})

@login_required_ajax
@transaction.commit_manually
def create(request):
    try:
        account = request.user.account
        if not account.is_admin():
            raise Exception("权限不足")
        params = json.loads(request.body)
        start = params.get("start")
        end = params.get("end")
        orgid = int(params.get("org"))
        tid = params.get("traffic")
        cost = float(params.get("cost",0))
        hours = params["hours"]
        areas = params["areas"]
        
        # 1.检查是否满足新建的条件
        if not check_resource(tid, start, end, hours, areas):
            raise Exception("分片不能重叠")  
        
        traffic = Traffic.objects.get(pk=tid)
        account = request.user.account 
        org=Organization.objects.get(pk=orgid)
        org_type=org.type
        if org_type!=0:
            datalist=get_current_balance([orgid],False)
            if datalist:
                org_data=datalist[0]
            else:
                raise Exception("获取实时余额失败，请检查业务服务器")           
        #非平台组织需检查余额  1.扣除组织余额,余额不足，返回错误信息
        media_type = traffic.position.media.type
        if org_type!=0:               
            org_in_balance=float(org_data["in_balance"])
            org_out_balance=float(org_data["out_balance"])
            org_ally_balance=float(org_data["ally_balance"])
            if media_type == 0:
                if org_in_balance < cost:
                    raise Exception("组织站内余额不足")                 
            elif media_type == 1:
                if org_out_balance < cost:
                    raise Exception("组织站外余额不足")
            else:
                if org_ally_balance < cost:
                    raise Exception("组织联盟余额不足")
        else:
            cost = 0         
        
         # 2.新建分片       
        resource = Resource()
        resource.name = ""
        resource.start = start
        resource.end = end
        resource.floor = 0       
        resource.traffic = traffic
        resource.allow_shared = False
        resource.save()        
        # 3.新建allocation        
        allocation = Allocation()
        allocation.resource = resource
        allocation.organization_id = orgid
        allocation.start = start
        allocation.end = end
        allocation.type = 0
        allocation.price = cost
        allocation.amount = 0
        allocation.priority = 0
        allocation.save()
        # 4.新建分片默认策略
        strategy = Strategy().default_strategy()
        strategy.priority=-5
        strategy.start = start
        strategy.end = end
        strategy.organization_id = orgid
        strategy.save()
        # 5.绑定默认策略
        resource_price = ResourcePrice()
        resource_price.resource = resource
        resource_price.strategy = strategy
        resource_price.price = 0
        resource_price.save()
        # 6.在分片上绑定地域和时间
        resource.set_resource_area(areas)        
        resource.set_resource_hour(hours)            
        # 7.将新建分片与流量的默认策略绑定        
        default_strategy = get_default_traffic_strategy({"tid":tid})       
        default_resource_price = ResourcePrice()
        default_resource_price.resource = resource
        default_resource_price.strategy = default_strategy
        default_resource_price.price = 0
        default_resource_price.save()      
        default_strategy.save()
        # 8.扣除记录
        now = datetime.datetime.now()
        cost_log = CostLog(deleted=False,organization_id=orgid, balance=cost, type=media_type, time=now, account=account, resource=resource)
        cost_log.save()
        
        operation_log=OperationLog()
        operation_log.operation="新建"
        operation_log.object="分片"
        operation_log.user=request.user
        operation_log.details="新建分片成功"      
        operation_log.object_id=resource.id
        operation_log.save()
    except Exception, ex:
        transaction.rollback()
        logger.exception(ex)
        return JsonResponseBadrequest({"message":str(ex)})
    else:
        transaction.commit()
    return JsonResponse({})
    
    
@login_required_ajax    
def get_resources(request):
    param = json.loads(request.body)
    searchTxt = param.get("search_text", "")
    pageNo = param.get('pageNo', 1)
    pageSize = param.get("pageSize", 10)
    tid = int(param.get("traffic", -1))
    start = param.get("start")
    end = param.get("end")
    state = param.get("state")
    org = request.user.account.get_organization()  
                
    args = []
    kwargs = {}
    if searchTxt:
        args.append(Q(RESOURCE__organization__name__icontains=searchTxt))
    if start and end :
        args.append(Q(start__range=(start, end)) | Q(end__range=(start, end)) | Q(start__lte=start, end__gte=end) | Q(start__gte=start, end__lte=end))
    kwargs['deleted'] = False
    kwargs['is_default']=False
    org_kwargs={}
    if not state:
        pass
    else:
        state=int(state)
        if state==0:
            kwargs["RESOURCE__organization"]=org  
        else:
            org_kwargs["RESOURCE__organization"]=org            
    result = {}
    try:    
        traffic = Traffic.objects.prefetch_related("position__attrs", "TRAFFIC", "position__media__attrs").select_related().get(pk=tid)
        default_resource = traffic.TRAFFIC.get(is_default=True)
        result['position_name'] = traffic.position.name 
        result['position_attrs'] = [attr.name for attr in traffic.position.attrs.all()]     
        result['width'] = traffic.position.width
        result['height'] = traffic.position.height    
        result['max'] = traffic.position.max   
        result['media_name'] = traffic.position.media.name
        result['media_attrs'] = [ attr.name for attr in traffic.position.media.attrs.all()]             
        result['floor'] = default_resource.floor
        result['start'] = traffic.start.strftime("%Y-%m-%d")
        result['end'] = traffic.end.strftime("%Y-%m-%d")
        result['bid_type'] = traffic_bid_type(traffic.bid_type)
        result['bid_price'] = traffic.bid_price
        result['pv'] = traffic.estimated_imp
        result['click'] = traffic.estimated_click
        result['shared']=is_traffic_shared(tid)
        if traffic.active:
            result['active'] = 1
        else:
            result['active'] = 0
        resources = traffic.TRAFFIC.filter(*args, **kwargs).exclude(**org_kwargs).order_by("-id").distinct()
        datalist = []
        paginator = Paginator(resources, pageSize)
        try:
            pageObj = paginator.page(pageNo)
        except PageNotAnInteger:
            pageObj = paginator.page(1)
        except EmptyPage:
            pageObj = paginator.page(paginator.num_pages)    
        for resource in pageObj.object_list:
            data = {}
            allocation = resource.RESOURCE.all()[0]
            data["id"] = resource.id
            data["start"] = resource.start
            data["end"] = resource.end
            data["hours"] = get_Field_list(resource.resourcehour_set.all(),"hour")
            data["areas"] = get_resource_area_name(resource)
            if org.type==0:
                data["cost"] = floatformat(allocation.price,arg=-2)
                data["org"] = allocation.organization.name            
            data["deleted"]=can_resource_deleted(resource.end)
            data["state"] = 0
            data["material"]=0
            if allocation.organization == org:
                data["state"] = 1
                data["cost"] = floatformat(allocation.price,arg=-2)
            default_strategy=get_default_resource_strategy(resource.id)
            if default_strategy.materialweight_set.all().exists():
                data["material"]=1
            datalist.append(data)
        result['bodyData'] = datalist
        result["pageNo"] = pageNo
        result["pageSize"] = pageSize
        result["totalCount"] = paginator.count    
        result["time"]=datetime.datetime.now().strftime("%Y-%m-%d")     
    except Exception, ex:
            logger.exception(ex)
            return JsonResponseBadrequest({"message":str(ex)})
    return JsonResponse(result)

def can_resource_deleted(end):
    deleted=0
    endTime = datetime.datetime(end.year,end.month,end.day)    
    now=datetime.datetime.now()
    nowTime=datetime.datetime(now.year,now.month,now.day)
    if nowTime< endTime:
         deleted=1
    return deleted    
        
# 新建分片与已存在的分片进行比对，若存在交集，则不予以创建
def check_resource(tid, start, end, hours, area_Ids):
    tag = True    
    args = []
    kwargs = {}
    # 1.根据日期筛选分片，并排除默认分片
    kwargs["deleted"] = False
    traffic = Traffic.objects.get(pk=tid)
    args.append(Q(start__range=(start, end)) | Q(end__range=(start, end)) | Q(start__lte=start, end__gte=end) | Q(start__gte=start, end__lte=end))
    resources = traffic.TRAFFIC.filter(*args, **kwargs).exclude(is_default=True)
    # 2.根据时间段进行下一步的筛选   
    obj_Ids=[]
   # objs= ResourceHour.objects.filter(resource__in=resources, hour__in=hours).distinct("resource")
    obj_Ids= ResourceHour.objects.filter(resource__in=resources, hour__in=hours).values_list('resource', flat=True).distinct()    
    # 3.根据地域进行下一步的筛选
    kwargs = {}
    kwargs["resource_id__in"] = obj_Ids
    kwargs["resource__deleted"] = False
    for areaId in area_Ids:
        args = []
        area = Area.objects.get(pk=areaId)
        code = area.code.encode("utf-8")
        condi = Q(id=-1)
        country = code[0:4]
        province = code[0:6]
        city = code[0:8]
        if code.endswith("000000"):
            condi = condi | Q(area__code__startswith=country)
        elif code.endswith("0000"):
            condi = condi | Q(area__code__startswith=province) | Q(area__code__startswith=country, area__code__endswith="000000")
        else:
            condi = condi | Q(area=area) | Q(area__code__startswith=province, area__code__endswith="0000") \
            | Q(area__code__startswith=country, area__code__endswith="000000")      
        args.append(condi)      
        if ResourceArea.objects.filter(*args,**kwargs).exists():
            tag = False
            break            
    return tag

def get_resource_areas(rid):
    datas=[]
    objs=ResourceArea.objects.filter(resource_id=rid)
    areasdata={}
    for obj in objs:
        data={}
        area=obj.area     
        data["id"]=area.id   
        data["name"]=area.name   
        datas.append(data)                 
    return datas

def get(request):
    result={}
    if request.method == "POST":
        params = request.POST
    else:
        params = request.GET
    try:
        rid=params.get("resource",-1)
        resource=Resource.objects.get(pk=rid)
        allocation=resource.RESOURCE.all()[0]
        org=allocation.organization
        result["id"]=rid
        result["start"]=resource.start
        result["end"]=resource.end
        result["hours"]=get_Field_list(resource.resourcehour_set.all(),"hour")
        result["areas"]=get_resource_areas(rid)
        result["org_id"]=org.id
        result["org_name"]=org.name
        result["cost"]=floatformat(allocation.price,arg=-2)
    except Exception, ex:
        logger.exception(ex)
        return JsonResponseBadrequest({"message":str(ex)})   
    return JsonResponse(result)


@login_required_ajax
@transaction.commit_manually
def update(request):
    result = {}
    try:
        account = request.user.account
        if not account.is_admin():
            raise Exception("权限不足")
        params = json.loads(request.body)
        rid = int(params.get("resource"))
        start = params.get("start")
        end = params.get("end")
        org_id =int(params.get("org"))
        cost = float(params.get("cost",0))
        hours = params["hours"]
        areas = params["areas"]
        
        
        resource = Resource.objects.get(pk=rid)
        resource.deleted = True  # 避免与原有的分片进行比对
        resource.save()
        traffic = resource.traffic
        tid = traffic.id
        # 1.检查是否满足修改的条件
        if not check_resource(tid, start, end, hours, areas):           
            raise Exception("分片不能重叠")          
        account = request.user.account               
        # 1.查看扣费记录，将扣费还原到对应账户类型，若满足扣费需求，则对相应的组织和扣除记录进行更新，否则不予以修改
        cost_log = CostLog.objects.get(deleted=False,resource=resource)
        old_cost=cost_log.balance
        old_org_id=cost_log.organization_id
        org=Organization.objects.get(pk=org_id)
        media_type = cost_log.type
        if org_id!=old_org_id:
            old_cost=0
        if org.type!=0:
            datalist=get_current_balance([org_id],False)
            org_data=datalist[0]
            if media_type==0:
                total=float(org_data["in_balance"])+old_cost
                if total < cost:
                    raise Exception("组织站内余额不足")
            elif media_type==1:
                total=float(org_data["out_balance"])+old_cost
                if total < cost:
                    raise Exception("组织站外余额不足")
            else:
                total=float(org_data["ally_balance"])+old_cost
                if total < cost:
                    raise Exception("组织联盟余额不足")
        else:
            cost=0   
        now = datetime.datetime.now()
        cost_log.balance=cost
        cost_log.organization=org
        cost_log.time=now
        cost_log.account=account
        cost_log.save()         
         # 2.修改分片       
        resource.deleted = False
        resource.start = start
        resource.end = end                 
        resource.set_resource_area(areas)        
        resource.set_resource_hour(hours)
        resource.save()   
        # 3.修改allocation        
        allocation = Allocation.objects.filter(resource=resource)[0]
        allocation.organization = org
        allocation.start = start
        allocation.end = end       
        allocation.price = cost
        allocation.save()
        # 4.修改默认策略
        strategy = get_default_resource_strategy(resource.id)
        strategy.start = start
        strategy.end = end
        strategy.organization = org
        strategy.save()
       
        operation_log=OperationLog()
        operation_log.operation="修改"
        operation_log.object="分片"
        operation_log.user=request.user
        operation_log.details="修改分片成功"      
        operation_log.object_id=rid
    except Exception, ex:
        transaction.rollback()
        logger.exception(ex)
        return JsonResponseBadrequest({"message":str(ex)})
    else:
        transaction.commit()
    return JsonResponse({})
@login_required_ajax   
@transaction.commit_manually
def delete(request):        
    try:
        account = request.user.account
        if not account.is_admin():
            raise Exception("权限不足")
        if request.method == "POST":
            params = request.POST
        else:
            params = request.GET
        rid = int(params.get("resource", -1))
        resource = Resource.objects.get(pk=rid)
        old_start=resource.start
        old_end=resource.end
        now = datetime.datetime.now()
        today = datetime.datetime(now.year,now.month,now.day)
        is_start=False
        if old_start<=today.date():
            is_start = True
        if is_start:       
            old_allocation=resource.RESOURCE.all()[0]
            old_org_id=old_allocation.organization_id
            old_cost=old_allocation.price
            days=(today.date()-old_start).days+1
            total_days=(old_end-old_start).days+1 
            new_cost=(old_cost/float(total_days))*days            
            
            cost_log=CostLog.objects.get(deleted=False,resource_id=rid)   
            cost_log.balance=new_cost
            cost_log.time=now            
            cost_log.account=request.user.account
            cost_log.save()                       
    
            old_allocation.price=new_cost
            old_allocation.end=today
            old_allocation.save() 
            resource.end=today
            resource.save()            
        else:            
            CostLog.objects.filter(resource_id=rid).update(deleted=True,time=now)          
            resource.deleted = True
            resource.RESOURCE.all().delete()
            resource.set_resource_area([])
            resource.set_resource_hour([])
            resource.resourceprice_set.all().delete()
            operation_log=OperationLog()
            operation_log.operation="删除"
            operation_log.object="分片"
            operation_log.user=request.user
            operation_log.details="删除分片成功"
            operation_log.object_id=rid        
    except Exception, ex:
        transaction.rollback()
        logger.exception(ex)
        return JsonResponseBadrequest({"message":str(ex)})
    else:
        transaction.commit()
    return JsonResponse({})

# 获取平台外的组织列表


def get_organizations(request):
#     param = json.loads(request.body)
#     searchTxt = param.get("search_text", "")
#     searchTxt = searchTxt.strip()    
#     pageSize = int(param.get("pageSize", 30))
#     pageNo = int(param.get("pageNo", 1))       

#     args = []
#     kwargs = {}    
#     if searchTxt :
#         args.append(Q(name__icontains=searchTxt) | Q(description__icontains=searchTxt))
    qset = Organization.objects.filter(deleted=False).order_by("-id")
#     paginator = Paginator(qset, pageSize)
#     try:
#         pageObj = paginator.page(pageNo)
#     except PageNotAnInteger:
#         pageObj = paginator.page(1)
#     except EmptyPage:
#         pageObj = paginator.page(paginator.num_pages)
        
    datalist = []
    result = {}
    for ele in qset:
        ele_n = {}
        ele_n["id"] = ele.id
        ele_n["text"] = ele.name  
        ele_n["type"] = ele.type           
        datalist.append(ele_n)   
#     result["pageNo"] = pageNo
#     result["pageSize"] = pageSize
#     result["totalCount"] = paginator.count
    result["bodyData"] = datalist
    return JsonResponse(result)

@login_required_ajax
def report(request):
    result = {}
    if request.method == "POST":
        params = request.POST
    else:
        params = request.GET
    account = request.user.account
    if account.is_admin():
        role=1
    elif account.is_vendor_user() or account.is_merchant_user() or account.is_platform_user():
        role=2 
    rid = int(params.get("resource",-1))       
    start = params.get("start")
    end = params.get("end")
    datalist=get_resource_dailyreport(rid,start,end,role)
    result["data"] = datalist    
    return JsonResponse(result)            

def get_materials(request):
    result = {}
    group = {}
    groupIds = []
    params = json.loads(request.body) 
    rid = params.get("resource")
    
    org=request.user.account.organization
    rp = ResourcePrice.objects.get(resource_id=rid,strategy__priority=-5)
    strategy=rp.strategy
    resource=rp.resource
    traffic_ids=[]
    traffic_ids.append(resource.traffic.id)
    params["traffic_ids"]=traffic_ids
    mws = strategy.materialweight_set.all()  
    groupWeights = mws.values('group').annotate(weight=Sum('weight'))
        
    for gw in groupWeights:
        groupName = gw["group"]
        weight = float(gw["weight"])
        if group.get(groupName) == None:
            group[groupName] = {}
            if group[groupName].get("materials") == None:
                group[groupName]["materials"] = []
                group[groupName]["weight"] = round(weight / 100)
                group[groupName]["name"] = groupName
    if mws.count() > 0:
        for mw in mws:
            m = mw.material
            data = {}
            data["id"] = m.id
            data["name"] = m.name
            data["width"] = m.width
            data["height"] = m.height
            data["status"] = m.status
            data["landingpage"] = m.landingpage
            data["tags"] = get_tag_name(m.tags.all())
            groupName = unicode(mw.group)               
            group[groupName]["materials"].append(data)
            groupIds.append(m.id)                            
        for (k, v) in  group.items():
            result["group"].append(v)
    
    results = get_materialData_By_Traffic(groupIds, params, org)      
    result["bodyData"] = results["bodyData"] 
    result["sizedata"] = results["sizedata"]
    result["pageNo"] = results["pageNo"]
    result["pageSize"] = results["pageSize"]
    result["totalCount"] = results["totalCount"]             
    return JsonResponse(result)


def get_resource_dailyreport(rid,start,end,role):
    datalist=[]
    start = datetime.datetime.strptime(start,"%Y-%m-%d").date()
    end = datetime.datetime.strptime(end,"%Y-%m-%d").date()
    objs = DailyResourceReport.objects.filter(resource_id=rid, date__range=(start, end)).order_by("date")\
           .values_list("date","pv","uv","click","cost")
    dateArr = date_range_array(start,end)
    resource_data_by_date ={}
    for pd in objs :
        d,pv,uv,click,cost=pd
        resource_data_by_date[d]=(pv,uv,click,cost)
    resource=Resource.objects.get(pk=rid)
    position_id=resource.traffic.position_id 
    for d in dateArr :
        pv,uv,click,income = resource_data_by_date.get(d,(0,0,0,0))
        data = {}
        data["pv"] = pv
        data["uv"] = uv
        data["click"] = click       
        data["ctr"]=0
        if pv !=0:
            data["ctr"]=floatformat(click / float(pv),arg=-5)
        data["date"] = d.strftime("%Y-%m-%d")   
        if role==1:
            data["cost"]=0
            position_report=DailyPositionReport.objects.filter(position_id=position_id,date=d)
            if position_report:
                position_pv=position_report[0].pv
                data["cost"]= floatformat(get_media_cost_by_resource(d,rid,pv,position_pv),arg=-2)
            data["sale_income"] = floatformat(get_cost_by_resource(d, rid),arg=-2)
            data["profit"]=floatformat(float(data["sale_income"])-float(data["cost"]),arg=-2)         
        datalist.append(data)  
    return datalist


    
    
    








    
    
    
